<?php
/**
 * 菜单管理
 */
declare (strict_types=1);

namespace app\api\controller;

use app\validate\Menus\Menu as MenuValidate;
use app\validate\Menus\Catalog as CatalogValidate;
use app\validate\Menus\Base as validate;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\facade\Log;
use think\Request;
use think\Response;
use think\response\Json;

class Menus
{
    /**
     * 显示资源列表
     *
     */
    public function adminList(Request $request)
    {
        $cache = $request->cache;
        // 根据缓存信息查询角色信息
        $role = Db::name('role')->find($cache['role']);
        $menu = Db::name('menu')->where('type', 'in', 'CATALOG,MENU')->where('id', 'in', implode(',', json_decode($role['menus'], true)))->order('sort')->select()->toArray();
//       return $menu;
        return success($this->dealMenuRoute($menu, 0));
    }

    /**获取所有菜单数据  树形结构
     */
    public function index()
    {
        try {
            if (isset($_REQUEST['keywords']) && !empty($_REQUEST['keywords'])) {
                $menus = Db::name('menu')->where('name', 'like', '%' . $_REQUEST['keywords'] . '%')->order('sort')->select()->toArray();
                return success($menus);
            } else {
                $menus = Db::name('menu')->order('sort')->select()->toArray();
                return success($this->dealMenuData($menus, 0));

            }
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
        }

    }

    /**
     * 获取树形数据作为下拉菜单数据源
     * @return Json|void
     */
    public function options()
    {
        try {
            $menus = Db::name('menu')->select()->toArray();
            return success($this->dealMenuOptions($menus, 0));
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
        }

    }

    /**
     * 保存新建的资源
     * @param Request $request
     * @return Json|void
     */
    public function save(Request $request)
    {
        // 接收参数
        $data = $request->post();

        // 根据菜单类型使用不同的校验规则

        $validate = match ($data['type']) {
            'CATALOG' => new CatalogValidate(),
            'MENU' => new MenuValidate(),
            default => new validate(),
        };

        // 执行校验
        if (!$validate->check($data)) {
            // 返回报错
            return error([], 9001, $validate->getError());
        } else {
            // 进行下一步操作
            if ($data['type'] == 'CATALOG') {
                $data['component'] = 'Layout';
            }
            $result = Db::name('menu')->save($data);
            if (!$result && $result !== 0) {
                return error([], 9004, '菜单添加失败');
            } else {
                try {
                    $menus = Db::name('menu')->select()->toArray();
                    return success($this->dealMenuData($menus, 0), 0, '菜单添加成功');
                } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
                }
            }
        }
    }

    /**
     * 显示指定的资源
     *
     * @param  $id
     * @return Response
     */
    public function read($id): Response
    {
        try {
            $data = Db::name('menu')->find($id);
            // 根据id查询 如果数据不为空
            if ($data != null) {
                return success($data);
            } else {
                return error([], 9002, '查询详细信息失败');
            }
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            return error([], 9002, '查询详细信息失败');
        }

    }

    /**
     * 显示编辑资源表单页.
     *
     * @param int $id
     * @return Response
     */
    public function edit($id)
    {
        //
        return 5;
    }

    /**
     * 保存更新的资源
     *
     * @param Request $request
     * @param int $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
        return 6;
    }

    /**
     * 删除指定资源
     *
     * @param  $id
     * @return Response
     * @throws DbException
     */
    public function delete($id): Response
    {
        $sonCount = Db::name('menu')->where(['parentId' => $id])->count('id');
        // 查询出父级为当前id的菜单的id
        $son = Db::name('menu')->where(['parentId' => $id])->field('id')->select()->toArray();
        $sonIds = [];
        foreach ($son as $item) {
            $sonIds[] = $item['id'];
        }
        $nextLevel = Db::name('menu')->where('parentId', 'in', $sonIds)->field('id')->select()->toArray();
        foreach ($nextLevel as $item) {
            $sonIds[] = $item['id'];
        }
        $sonIds[] = $id;

        $result = Db::name('menu')->delete($sonIds);
        if (!$result) {
            return error([], 9004, '删除失败');
        } else {
            return success([], 0, '删除成功');
        }
    }

    public function routes()
    {
        return 8888;
    }

    /**
     * 处理菜单树形数据
     * @param $data
     * @param $pid
     * @return array
     */
    private function dealMenuData(array $data, int $pid = 0): array
    {
        $branch = [];
        foreach ($data as $element) {
            if ($element['parentId'] == $pid) {
                $children = $this->dealMenuData($data, $element['id']);
                if ($children) {
                    $element['children'] = $children;
                }
                $branch[] = $element;
            }
        }
        return $branch;
    }

    /**
     * 处理菜单数据作为下拉菜单数据源
     * @param array $data
     * @param int $pid
     * @return array
     */
    private function dealMenuOptions(array $data, int $pid = 0): array
    {
        $branch = [];
        foreach ($data as $element) {
            if ($element['parentId'] == $pid) {
                $children = $this->dealMenuOptions($data, $element['id']);
                if ($children) {
                    $element['children'] = $children;
                }
                $newData = array(
                    'label' => $element['name'],
                    'value' => $element['id'],
                );
                if (isset($element['children']) && count($element['children']) > 0) {
                    $newData['children'] = $element['children'];
                }
                $branch[] = $newData;
            }
        }
        return $branch;
    }

    /**处理菜单作为前端路由数据
     * @param array $data
     * @param int $pid
     * @return array
     */
    private function dealMenuRoute(array $data, int $pid = 0): array
    {
        $branch = [];
        foreach ($data as $element) {
            if ($element['parentId'] == $pid) {
                $children = $this->dealMenuRoute($data, $element['id']);
                if ($children) {
                    $element['children'] = $children;
                }
                if ($element['type'] == 'CATALOG') {
                    $newData = array(
                        'component' => 'Layout',
                        'path' => $element['routePath'] ?: '',
                        'redirect' => $element['redirect'],
                        'name' => $element['routeName'] ?: '',
                        'meta' => array(
                            'alwaysShow' => false,
                            'hidden' => $element['visible'] == 0,
                            'icon' => $element['icon'],
                            'params' => null,
                            'title' => $element['name']
                        ),
                    );
                }
                if ($element['type'] == 'MENU') {
                    $newData = array(
                        'component' => $element['component'],
                        'path' => $element['routePath'] ?: '',
                        'name' => $element['routeName'] ?: '',
                        'meta' => array(
                            'alwaysShow' => false,
                            'hidden' => $element['visible'] == 0,
                            'icon' => $element['icon'],
                            'params' => null,
                            'keepAlive' => $element['keepAlive'] == 1,
                            'title' => $element['name']
                        ),
                    );
                }


                if (isset($element['children']) && count($element['children']) > 0) {
                    $newData['children'] = $element['children'];
                }
                $branch[] = $newData;
            }
        }
        return $branch;
    }
}